package com.wstuo.common.rules;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.agent.KnowledgeAgent;
import org.drools.agent.KnowledgeAgentConfiguration;
import org.drools.agent.KnowledgeAgentFactory;
import org.drools.io.Resource;
import org.drools.io.ResourceChangeScannerConfiguration;
import org.drools.io.ResourceFactory;
import org.drools.io.impl.ByteArrayResource;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.Activation;
import org.drools.runtime.rule.AgendaFilter;
import com.wstuo.common.rules.drool.RulePathType;
import com.wstuo.common.security.utils.AppConfigUtils;
import com.wstuo.multitenancy.TenantIdResolver;

/**
 * DROOLS规则门户方法
 * 
 * @author QXY
 * 
 */
public class DroolsFacade {
	private TenantIdResolver tr=new TenantIdResolver();
	
	@SuppressWarnings("serial")
	static Map<String,KnowledgeAgent> kaMap = new HashMap<String,KnowledgeAgent>(){
		{
			put(RulePathType.Request.getValue(),null);
			put(RulePathType.RequestMail.getValue(),null);
			put(RulePathType.RequestWorkFlow.getValue(),null);
			put(RulePathType.Change.getValue(),null);
			put(RulePathType.Sla.getValue(),null);
		}
	};
	
	/**
	 * Get the KnowledgeAgent and make it scan the resources per 5 seconds
	 * @param  key 
	 * @return KnowledgeAgent
	 */
	public KnowledgeAgent getKnowledgeAgent(String key,String ruleResourcePath) {
		KnowledgeAgent kagent = kaMap.get(key+"-"+tr.resolveCurrentTenantIdentifier());
		if(kagent==null){
			ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
			sconf.setProperty("drools.resource.scanner.interval", "5");
			ResourceFactory.getResourceChangeScannerService().configure(sconf);
			ResourceFactory.getResourceChangeScannerService().start();
			ResourceFactory.getResourceChangeNotifierService().start();

			KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
			aconf.setProperty("drools.agent.scanDirectories", "true");
			aconf.setProperty("drools.agent.newInstance", "true");

			KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
			kagent = KnowledgeAgentFactory.newKnowledgeAgent("MyAgent", kbase, aconf);
			
			
			//获取管理路径
			String filepath=AppConfigUtils.getInstance().getFileManagementPath()+tr.resolveCurrentTenantIdentifier()+"/";
			
			//设置规则ChangeSet资源
			String changeSetString="<change-set " +
					"xmlns='http://drools.org/drools-5.0/change-set'  " +
					"xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'  " +
					"xs:schemaLocation='http://drools.org/drools-5.0/change-set  " +
					"http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >" +
					"<add>" + 
					"<resource type=\"DRL\" source=\"file:"+filepath+ruleResourcePath+"\" />"+
					"</add>"+ 
					"</change-set>";
		    Resource changeSetRes=new ByteArrayResource(changeSetString.getBytes());
			kagent.applyChangeSet(changeSetRes);
			kaMap.put(key+"-"+tr.resolveCurrentTenantIdentifier(), kagent);
		}
		return kagent;
	}

	
	/**
	 * get knowledge base
	 * @param key 
	 * @return KnowledgeBase
	 */
	public KnowledgeBase getKnowledgeBase(String key,String ruleResourcePath) {
		KnowledgeAgent kagent = getKnowledgeAgent(key,ruleResourcePath);
		KnowledgeBase kbase = kagent.getKnowledgeBase();
		return kbase;
	}

	
	/**
	 * 规则匹配
	 * @param key 
	 * @param obj
	 * @param rulePackageNames 过滤的规则包名称
	 */
	public void matchRule(Object obj, String[] rulePackageNames,String key,String ruleResourcePath) {
		KnowledgeBase kbase = getKnowledgeBase(key,ruleResourcePath);
		StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		ksession.insert(obj);

		if ((rulePackageNames != null) && (rulePackageNames.length > 0)) {
			ksession.fireAllRules(new RulesFilter(rulePackageNames));
		} else {
			ksession.fireAllRules();
		}

		ksession.dispose();
	}
	
	/**
	 * 规则匹配
	 * @param key 
	 * @param objs
	 * @param rulePackages 过滤的规则包名称
	 */
	public void matchRules(List<? extends Object> objs, String[] rulePackageNames,String key,String ruleResourcePath) {
		KnowledgeBase kbase = getKnowledgeBase(key,ruleResourcePath);
		StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		for (Object obj : objs) {
			ksession.insert(obj);
		}
		if ((rulePackageNames != null) && (rulePackageNames.length > 0)) {
			ksession.fireAllRules(new RulesFilter(rulePackageNames));
		} else {
			ksession.fireAllRules();
		}

		ksession.dispose();
	}


	
	public class RulesFilter implements AgendaFilter {
		private List<String> rulePackageNameList;

		// 构造函数,传入条件
		public RulesFilter(String... rulePackageNames) {
			rulePackageNameList = Arrays.asList(rulePackageNames);
		}

		public boolean accept(Activation activation) {
			boolean result = false;
			String rname = activation.getRule().getPackageName().trim();

			if (rulePackageNameList.contains(rname)) {
				result = true;
			}
			return result;
		}
	}
	
}
